#include <iostream>

using namespace std;
// 引用
// 作用：给变量起别名
// 语法：数据类型 &别名 = 原名
//本质：引用的本质在C++内部实现是一个指针常量

// 引用作函数参数
// 作用：函数传参时，可以利用引用的技术让行参修饰实参
// 优点：可以简化指针修改实参

// 1.值传递
void mySwap01(int a, int b){
    int temp = a;
    a = b;
    b = temp;
    cout << "mySwap01  d = " << a << endl;
    cout << "mySwap01  e = " << b << endl;
}

// 2.地址传递
void mySwap02(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 3.引用传递
void mySwap03(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}

//引用做函数返回值
//作用:引用是可以作为函数的返回值存在的
//注意：不要返回局部变量引用
//用法：函数调用作为左值

//返回局部变量引用
// int &test01(){
//     int a = 10; //局部变量，存放在四区中的 栈区
//     return a;
// }

//返回静态变量引用
int &test02(){
    static int a = 20;  //静态变量，存放在全局区，全局区上的数据在程序结束后系统释放
    return a;
}


//打印数据函数
void showValue(const int &val){ //加入const防止误操作
    //val = 1000;
    cout << "val =" << val << endl;
}

int main(){
    int a = 10;
    int &b = a;     
    // b = 20;              //内部发现b是引用，自动帮我们转换为：*b = 20；
    // int &c           //错误，引用必须要初始化
    // 引用一旦初始化后，，就不可以更改了  例如之前是a的别名 后面改成b的别名
    int c = 20;
    // b = c; //赋值操作，而不是更改引用
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    int d = 10;
    int e = 20;
    // mySwap01(d, e);
    // mySwap02(&d, &e);
    mySwap03(d, e);
    cout << "d = " << d << endl;
    cout << "e = " << e << endl;


    // int &ref = test01();
    int &ref = test02();
    cout << "ref = " << ref << endl;
    test02() = 1000;            //如果函数的返回值是引用，这个函数调用可以作为左值
    cout << "ref = " << ref << endl;
    

    //常量引用
    //使用场景：用来修饰行参，防止误操作
    //int a = 10;
    //int &ref = 10; //错误 引用必须引一块合法的内存空间
    //加上const之后，编译器将代码修改 int temp = 10; const int &ref = temp;
    //const int &ref = 10;
    //ref = 20 //加入const之后变为只读，不可修改
    
    int f = 100;
    showValue(f);
    cout << "f = " << f << endl;


    system("pause");
    return 0;
}
